# -*- coding:utf-8 -*-
"""
配置（读取配置）文件
1、数据库配置缓存，避免频繁访问数据库
2、配合变动通知，主动更新缓存 post方法
3、支持定时读取配置文件（llt配置）
4、读写锁 Successfully installed readerwriterlock==1.0.9
"""
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
from cachetools import cached, LRUCache, TTLCache,cachedmethod
from cachetools.keys import hashkey
# from timer import calculate_function_run_time
import operator, urllib
import urllib.request
import json
import threading
import time
import datetime
from readerwriterlock import rwlock
from threading import Timer
import re
# from utilities.log_help import LogHelper,TraceHelper,DebugHelper
class SingletonGlobalVariable(object):
    _instance_lock = threading.Lock()
    def __init__(self, *args, **kwargs):
        # time.sleep(1)
        pass
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            with SingletonGlobalVariable._instance_lock:
                if not hasattr(cls, '_instance'):
                    SingletonGlobalVariable._instance = super().__new__(cls)
        return SingletonGlobalVariable._instance
class CachedPEPs(SingletonGlobalVariable):
    def __init__(self, cachesize, cachettl):
        self.cache = TTLCache(maxsize=cachesize, ttl=cachettl)
        # self.cache = LRUCache(maxsize=cachesize)
        self.marker = rwlock.RWLockFair()
        self.read_marker = self.marker.gen_rlock()
        self.write_marker = self.marker.gen_wlock()
    # @cachedmethod(operator.attrgetter('cache'))
    def _get(self, num): # 从原始数据库获取数据
        """Retrieve text of a Python Enhancement Proposal"""
        url = 'http://www.python.org/dev/peps/pep-%04d/' % num
        with urllib.request.urlopen(url) as s:
            time.sleep(2)
            return s.read()
    def get(self, *args, **kwargs):
        # 由于cache 使用keys.hashkey(*args, **kwargs) 作为缓存键 要清空缓存，保持一致
        k = hashkey(*args, **kwargs)
        self.read_marker.acquire()
        try:
            return self.cache[k]
        except KeyError:
            pass  # key not found
        self.read_marker.release()
        v = self._get(*args, **kwargs)
        if self.write_marker.acquire(blocking=True, timeout=0.5):
            try:
                #Do stuff
                self.cache.setdefault(k, v)        
            except KeyError:
                pass  # value too large
            finally:
                self.write_marker.release()
        return v  
    # 使用原始数据并更新缓存
    def post(self, *args, **kwargs):
        # 由于cache 使用keys.hashkey(*args, **kwargs) 作为缓存键 要清空缓存，保持一致
        k = hashkey(*args, **kwargs)
        try:
            self.cache.pop(k)
        except KeyError:
            pass  # key not found
        return self.get(*args, **kwargs)
peps = CachedPEPs(cachesize=20,cachettl=5)
while True:
    print("______________--PEP #1:")
    print("______________--PEP #1:")
    print("______________--PEP #1:")
    print("______________--PEP #1:")
    print("PEP #1: %s" % peps.get(1))
    time.sleep(3)